#include "xsane.h"
#include "xsane-back-gtk.h"
#include "xsane-curve.h"
#include "xsane-device-options-window.h"
#include "xsane-device-preferences.h"
#include "xsane-email-project.h"
#include "xsane-fax-project.h"
#include "xsane-front-gtk.h"
#include "xsane-gamma.h"
#include "xsane-gammacurve.h"
#include "xsane-main-window.h"
#include "xsane-multipage-project.h"
#include "xsane-ui.h"

/* ---------------------------------------------------------------------------------------------------------------------- */

static int xsane_scanmode_number[] = { XSANE_VIEWER, XSANE_SAVE, XSANE_COPY, XSANE_MULTIPAGE, XSANE_FAX, XSANE_EMAIL };

/* ---------------------------------------------------------------------------------------------------------------------- */

/* connect to backend and create main dialogs:
 - sane_open
 - create dialog xsane.main_window
 -   build menues
 - create dialog xsane.device_options.window
 - create tooltip style
 - create dialog xsane.main_window_right_pane
 - create dialog xsane.gamma_dialog
 - create dialog xsane.batch_scan
 - create dialog xsane.preview
*/

// open the selected device
// initialize xsane.device_options.dev, xsane.device_options.num_elements, xsane.device_options.dev_name
static void xsane_open_device()
{
  const gchar *devname;
  SANE_Status status;
  SANE_Handle sane_handle;
  char buf[TEXTBUFSIZE];

  devname = xsane.devlist[xsane.selected_dev]->name;

  status = sane_open(devname, &sane_handle);
  xsane.device_options.dev = (void **)sane_handle;

  if (status != SANE_STATUS_GOOD)
  {
    snprintf(buf, sizeof(buf), "%s `%s':\n %s.", ERR_DEVICE_OPEN_FAILED, devname, XSANE_STRSTATUS(status));
    xsane_back_gtk_error(buf, TRUE);
    xsane_exit();
    /* will never come to here */
  }

  if (sane_control_option(xsane.device_options.dev, 0, SANE_ACTION_GET_VALUE, &xsane.device_options.num_elements, 0) != SANE_STATUS_GOOD)
  {
    xsane_back_gtk_error(ERR_OPTION_COUNT, TRUE);
    sane_close(xsane.device_options.dev);
    xsane_exit();
    /* will never come to here */
  }

  xsane.device_options.dev_name = strdup(devname);
}

// initialize xsane.backend_name and xsane.backend_name_translation
static void xsane_init_backend_name()
{
  char buf[TEXTBUFSIZE];
  char *textptr;

  snprintf(buf, sizeof(buf), "%s", xsane.devlist[xsane.selected_dev]->name);	/* generate "sane-BACKENDNAME" */
  textptr = strrchr(buf, ':'); /* format is midend:midend:midend:backend:device or backend:device */
  if (textptr)
  {
    *textptr = 0; /* erase ":device" at end of text */
    textptr  = strrchr(buf, ':');
    if (textptr) /* midend:backend:device */
    {
      textptr++;
    }
    else /* backend:device */
    {
      textptr = buf;
    }

    xsane.backend_name = (char *)malloc(strlen(textptr)+6);
    sprintf(xsane.backend_name, "sane-%s", textptr); /* add "sane-" */
    DBG(DBG_info, "Setting backend name \"%s\"\n", xsane.backend_name);

    xsane.backend_name_translation = xsane.backend_name;
    bindtextdomain(xsane.backend_name_translation, STRINGIFY(SANELOCALEDIR)); /* set path for backend translation texts */
#if defined(HAVE_GTK2) && ENABLE_NLS
    bind_textdomain_codeset(xsane.backend_name_translation, "UTF-8");
#endif

    if (!strlen(dgettext(xsane.backend_name_translation, ""))) /* translation not valid, use general translation table */
    {
      xsane.backend_name_translation = (char *)"sane-backends";
      DBG(DBG_info, "Setting general translation table \"sane-backends\" with localedir: %s\n", STRINGIFY(LOCALEDIR));
    }
    else /* we have a valid table for the backend */
    {
      DBG(DBG_info, "Setting backend translation table \"%s\" with localedir: %s\n", xsane.backend_name_translation, STRINGIFY(LOCALEDIR));
    }
  }
  else /* use general backend name "sane-backends" for sane */
  {
    xsane.backend_name = strdup("sane-backends");
    DBG(DBG_info, "Setting general backend name \"%s\"\n", xsane.backend_name);

    xsane.backend_name_translation = xsane.backend_name;
    DBG(DBG_info, "Setting general translation table \"sane-backends\" with localedir: %s\n", STRINGIFY(LOCALEDIR));
  }

  bindtextdomain("sane-backends", STRINGIFY(SANELOCALEDIR)); /* set path for backend translation texts */
#ifdef HAVE_GTK2
  bind_textdomain_codeset(xsane.backend_name_translation, "UTF-8");
#endif
}

// initialize xsane.device_text
static void xsane_init_device_text(void)
{
  char devicetext[TEXTBUFSIZE];
  char *textptr;
  char buf[TEXTBUFSIZE];

  /* create device-text for window titles */

  snprintf(devicetext, sizeof(devicetext), "%s", xsane.devlist[xsane.selected_dev]->model);
  textptr = devicetext + strlen(devicetext);
  while (*(textptr-1) == ' ') /* erase spaces at end of text */
  {
    textptr--;
  }

  *textptr = ':';
  textptr++;
  *textptr = 0;

  if (!strncmp(xsane.device_options.dev_name, "net:", 4)) /* network device ? */
  {
    sprintf(textptr, "net:");
    textptr = devicetext + strlen(devicetext);
  }

  snprintf(buf, sizeof(buf), ":%s", xsane.device_options.dev_name);
  snprintf(buf, sizeof(buf), "/%s", (strrchr(buf, ':')+1));
  sprintf(textptr, "%s", (strrchr(buf, '/')+1));

  xsane.device_text = strdup(devicetext);
}

// initializes xsane.device_set_filename
void xsane_init_dev_pref_filename()
{
  char buf[TEXTBUFSIZE];

  /* if no preferences filename is given on commandline, create one from devicenaname */
  if (xsane.device_set_filename == NULL)
  {
    if (!strcmp(xsane.devlist[xsane.selected_dev]->vendor, TEXT_UNKNOWN))
    {
      snprintf(buf, sizeof(buf), "%s",  xsane.devlist[xsane.selected_dev]->name);
    }
    else
    {
      snprintf(buf, sizeof(buf), "%s:%s", xsane.devlist[xsane.selected_dev]->vendor, xsane.devlist[xsane.selected_dev]->model);
    }
    xsane.device_set_filename = strdup(buf); /* set preferences filename */
  }
}

/* ---------------------------------------------------------------------------------------------------------------------- */

static void xsane_device_preferences_restore(void)
{
 char filename[PATH_MAX];
 struct stat st; 

  DBG(DBG_proc, "xsane_device_preferences_restore\n");
printf( "xsane_device_preferences_restore\n");

  xsane_back_gtk_make_path(sizeof(filename), filename, "xsaner", 0, 0, xsane.device_set_filename, ".drc", XSANE_PATH_LOCAL_SANE);

  if (stat(filename, &st) >= 0)
  {   
    xsane_device_preferences_load_file(filename);
  }
  else /* no local sane file, look for system file */
  {
    xsane_back_gtk_make_path(sizeof(filename), filename, "xsane", 0, 0, xsane.device_set_filename, ".drc", XSANE_PATH_SYSTEM);
    xsane_device_preferences_load_file(filename);
  }
printf( "done xsane_device_preferences_restore\n");
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_build_ui()
{

  DBG(DBG_proc, "xsane_build_ui\n");
printf( "*** CREATE ***\n");
printf( "xsane_build_ui\n");

  xsane_open_device();
  xsane_init_backend_name();
  xsane_init_device_text();
  xsane_init_dev_pref_filename();

  xsane_device_preferences_restore();	/* restore device-settings */

  /* fill in dialog structure */
  xsane.device_options.element  = (DialogElement *)malloc(xsane.device_options.num_elements * sizeof(xsane.device_options.element[0]));
  memset(xsane.device_options.element, 0, xsane.device_options.num_elements * sizeof(xsane.device_options.element[0]));

  xsane_create_main_window();

/* create the scanner device options dialog box */
  xsane_create_device_options_window();

  /* create gamma dialog and set colors */
  xsane_create_gamma_dialog(xsane.device_text); /* create the free gamma curve dialog */

  /* create batch_scan dialog */
  xsane_create_batch_scan_dialog(xsane.device_text);

  if (xsane.batch_scan_load_default_list)
  {
   char filename[PATH_MAX];

    DBG(DBG_proc, "batch_scan:load default list\n");
    xsane_back_gtk_make_path(sizeof(filename), filename, "xsaner", "batch-lists", 0, "default", ".xbl", XSANE_PATH_LOCAL_SANE);
    xsane_batch_scan_load_list_from_file(filename);

    xsane.batch_scan_load_default_list = 0; /* mark list is loaded, we only want to load the list at program startup */
  }

printf( "*** DONE CREATE ***\n");

  // show windows
  {
    xsane_restore_windows_sizes();

    gtk_widget_realize(xsane.device_options.window); /* is needed for saving window geometry */

    if (preferences.show_device_options)
    {
      gtk_widget_show(xsane.device_options.window);
    }

    if (preferences.show_batch_scan)
    {
      gtk_widget_show(xsane.batch_scan_dialog);
    }

    gtk_widget_show(xsane.main_window); /* call as last so focus is on it */
  }

printf( "\n*** UPDATE ***\n");

  while (gtk_events_pending())
  {
    gtk_main_iteration();
  }

  xsane_update_gamma_curve(TRUE);
  xsane_refresh_dialog();

  preview_update_surface(xsane.preview, 1);

  xsane_enhancement_by_gamma();

printf( "*** DONE UPDATE ***\n");
printf( "done xsane_build_ui\n");
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_create_main_window()
{
  GdkColormap *colormap;
  GtkWidget *main_window_menu_body;
  GtkStyle *current_style;
  char windowname[TEXTBUFSIZE];

  /* create the xsane main window */
  {
    xsane.main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_move(GTK_WINDOW(xsane.main_window), XSANE_MAIN_WINDOW_POS_X, XSANE_MAIN_WINDOW_POS_Y);
    gtk_window_set_resizable(GTK_WINDOW(xsane.main_window), TRUE);

    g_signal_connect(GTK_OBJECT(xsane.main_window), "delete_event", GTK_SIGNAL_FUNC(xsane_scan_win_delete), NULL);

    sprintf(windowname, "%s %s %s", xsane.prog_name, XSANE_VERSION, xsane.device_text);
    gtk_window_set_title(GTK_WINDOW(xsane.main_window), (char *) windowname);
    xsane_set_window_icon(xsane.main_window, 0);
  }

  /* create the xsane main window accelerator table */
  {
    xsane.accelerator_group = gtk_accel_group_new();
    gtk_window_add_accel_group(GTK_WINDOW(xsane.main_window), xsane.accelerator_group); 
  }

  // tooltips
  {
    /* define tooltips colors */

    xsane.tooltips = gtk_tooltips_new();
    colormap = gdk_drawable_get_colormap(xsane.main_window->window);

    /* use black as foreground: */
    xsane.tooltips_fg.red   = 0;
    xsane.tooltips_fg.green = 0;
    xsane.tooltips_fg.blue  = 0;
    gdk_color_alloc(colormap, &xsane.tooltips_fg);

    /* postit yellow (khaki) as background: */
    xsane.tooltips_bg.red   = 61669;
    xsane.tooltips_bg.green = 59113;
    xsane.tooltips_bg.blue  = 35979;
    gdk_color_alloc(colormap, &xsane.tooltips_bg);

    gtk_tooltips_force_window(xsane.tooltips);

    current_style = gtk_style_copy(gtk_widget_get_style(xsane.tooltips->tip_window));
    current_style->bg[GTK_STATE_NORMAL] = xsane.tooltips_bg;
    current_style->fg[GTK_STATE_NORMAL] = xsane.tooltips_fg;
    gtk_widget_set_style(xsane.tooltips->tip_window, current_style);  

    xsane_back_gtk_set_tooltips(preferences.tooltips_enabled);
  }

  // style
  {
    GtkStyle *style;
    style = gtk_widget_get_style(xsane.main_window);
  /*
    style = gtk_rc_get_style(xsane.main_window);
    style = gtk_widget_get_default_style();
  */

    xsane.gc_trans = style->bg_gc[GTK_STATE_NORMAL];
    xsane.bg_trans = &style->bg[GTK_STATE_NORMAL];   
  }

  // colormap and gc
  {
    GdkColormap *colormap;
    GdkColor color_black;
    GdkColor color_red;
    GdkColor color_green;
    GdkColor color_blue;
    GdkColor color_backg;

    colormap = gdk_drawable_get_colormap(xsane.main_window->window);

    xsane.gc_black  = gdk_gc_new(xsane.main_window->window);
    color_black.red   = 0;
    color_black.green = 0;
    color_black.blue  = 0;
    gdk_color_alloc(colormap, &color_black);
    gdk_gc_set_foreground(xsane.gc_black, &color_black);

    xsane.gc_red   = gdk_gc_new(xsane.main_window->window);
    color_red.red   = 40000;
    color_red.green = 10000;
    color_red.blue  = 10000;
    gdk_color_alloc(colormap, &color_red);
    gdk_gc_set_foreground(xsane.gc_red, &color_red);

    xsane.gc_green = gdk_gc_new(xsane.main_window->window);
    color_green.red   = 10000;
    color_green.green = 40000;
    color_green.blue  = 10000;
    gdk_color_alloc(colormap, &color_green);
    gdk_gc_set_foreground(xsane.gc_green, &color_green);

    xsane.gc_blue  = gdk_gc_new(xsane.main_window->window);
    color_blue.red   = 10000;
    color_blue.green = 10000;
    color_blue.blue  = 40000;
    gdk_color_alloc(colormap, &color_blue);
    gdk_gc_set_foreground(xsane.gc_blue, &color_blue);

    xsane.gc_backg  = gdk_gc_new(xsane.main_window->window);
    color_backg.red   = 50000;
    color_backg.green = 50000;
    color_backg.blue  = 50000;
    gdk_color_alloc(colormap, &color_backg);
    gdk_gc_set_foreground(xsane.gc_backg, &color_backg);                              
  }



  /* set the main vbox */
  {
    main_window_menu_body = gtk_vbox_new(FALSE, 0);
    gtk_container_set_border_width(GTK_CONTAINER(main_window_menu_body), 0);
    gtk_container_add(GTK_CONTAINER(xsane.main_window), main_window_menu_body);
    gtk_widget_show(main_window_menu_body);

    /* create the main_window_menu_bar */
    {
      GtkWidget *menubar_item;

      xsane.main_window_menu_bar = gtk_menu_bar_new();
      gtk_box_pack_start(GTK_BOX(main_window_menu_body), xsane.main_window_menu_bar, FALSE, FALSE, 0);
      gtk_widget_show(xsane.main_window_menu_bar);

      /* "Files" submenu: */
      menubar_item = gtk_menu_item_new_with_label(MENU_FILE);
      gtk_container_add(GTK_CONTAINER(xsane.main_window_menu_bar), menubar_item);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_files_build_menu());
    /*  gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_F, (GdkModifierType)0, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED)); */
      gtk_widget_show(menubar_item);

      /* "Preferences" submenu: */
      menubar_item = gtk_menu_item_new_with_label(MENU_PREFERENCES);
      gtk_container_add(GTK_CONTAINER(xsane.main_window_menu_bar), menubar_item);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_preferences_build_menu());
    /*  gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_P, (GdkModifierType)0, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED)); */
      gtk_widget_show(menubar_item);

      /* "View" submenu: */
      menubar_item = gtk_menu_item_new_with_label(MENU_VIEW);
      gtk_container_add(GTK_CONTAINER(xsane.main_window_menu_bar), menubar_item);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_view_build_menu());
    /*  gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_V, (GdkModifierType)0, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED)); */
      gtk_widget_show(menubar_item);


      /* "Window" submenu: */
      menubar_item = gtk_menu_item_new_with_label(MENU_WINDOW);
      gtk_container_add(GTK_CONTAINER(xsane.main_window_menu_bar), menubar_item);
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_window_build_menu());
    /*  gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_V, (GdkModifierType)0, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED)); */
      gtk_widget_show(menubar_item);


      /* "Help" submenu: */
      menubar_item = gtk_menu_item_new_with_label(MENU_HELP);
      gtk_container_add(GTK_CONTAINER(xsane.main_window_menu_bar), menubar_item);
     /*  gtk_menu_item_right_justify((GtkMenuItem *) menubar_item); */
      gtk_menu_item_set_submenu(GTK_MENU_ITEM(menubar_item), xsane_help_build_menu());
    /*  gtk_widget_add_accelerator(menubar_item, "select", xsane.accelerator_group, GDK_H, (GdkModifierType)0, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED)); */
      gtk_widget_show(menubar_item);
    }

    {
      xsane.main_window_body = gtk_hbox_new(FALSE, 5);
      gtk_widget_show(xsane.main_window_body);
      gtk_container_set_border_width(GTK_CONTAINER(xsane.main_window_body), 5);
      gtk_container_add(GTK_CONTAINER(main_window_menu_body), xsane.main_window_body);          

      xsane.main_window_hpaned1 = gtk_hpaned_new();
      gtk_widget_show(xsane.main_window_hpaned1);
      gtk_container_add(GTK_CONTAINER(xsane.main_window_body), xsane.main_window_hpaned1);

      xsane.main_window_hpaned2 = gtk_hpaned_new();
      gtk_widget_show(xsane.main_window_hpaned2);
      gtk_paned_pack1(GTK_PANED(xsane.main_window_hpaned1), xsane.main_window_hpaned2, TRUE/*resize*/, TRUE/*shrink*/);
    }
  }

  /* create left pane */
  xsane.main_window_left_pane = xsane_build_main_window_left_pane();
  gtk_paned_pack1(GTK_PANED(xsane.main_window_hpaned2), xsane.main_window_left_pane, FALSE/*resize*/, TRUE/*shrink*/);

  /* create histogram dialog and set colors */
  xsane.main_window_right_pane = xsane_build_main_window_right_pane();
  gtk_paned_pack2(GTK_PANED(xsane.main_window_hpaned1), xsane.main_window_right_pane, FALSE/*resize*/, TRUE/*shrink*/);

  xsane.preview = preview_new();
}


/* ---------------------------------------------------------------------------------------------------------------------- */

GtkWidget *xsane_build_main_window_left_pane()
{
  GtkWidget *main_window_left_pane;

  main_window_left_pane = gtk_scrolled_window_new(NULL, NULL);
  gtk_widget_show(main_window_left_pane);
  gtk_widget_set_size_request(main_window_left_pane, 280, -1);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_window_left_pane),
                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

  {
    GtkWidget *main_window_left_pane_vbox;

    main_window_left_pane_vbox = gtk_vbox_new(FALSE, 0);
    gtk_widget_show(main_window_left_pane_vbox);
    gtk_container_set_border_width(GTK_CONTAINER(main_window_left_pane_vbox), 5);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_window_left_pane), main_window_left_pane_vbox);

    // xsane.scan_mode_medium.container
    {
      xsane.scan_mode_medium.container = gtk_vbox_new(/* homogeneous */ FALSE, 0);
      gtk_box_pack_start(GTK_BOX(main_window_left_pane_vbox), xsane.scan_mode_medium.container, FALSE, FALSE, 0);
      gtk_widget_show(xsane.scan_mode_medium.container);
    }

    xsane_create_scan_mode_medium_box();
    gtk_container_add(GTK_CONTAINER(xsane.scan_mode_medium.container), xsane.scan_mode_medium.body);

    /* create the progress bar / info box, scan and cancel button */
    {
      GtkWidget *scan_button_box;

      scan_button_box = gtk_hbox_new(FALSE, 6);
      gtk_box_pack_end(GTK_BOX(main_window_left_pane_vbox), scan_button_box, FALSE, FALSE, 8);
      gtk_widget_show(scan_button_box);

      {
        GtkWidget *scan_button_table;

        scan_button_table = gtk_table_new(2, 2, FALSE);
        gtk_box_pack_start(GTK_BOX(scan_button_box), scan_button_table, TRUE, TRUE, 8);
        gtk_widget_show(scan_button_table);

        gtk_table_set_row_spacings(GTK_TABLE(scan_button_table), 6);
        gtk_table_set_col_spacings(GTK_TABLE(scan_button_table), 6);


        /* Info frame */
        {
          GtkWidget *info_frame;

          info_frame = gtk_frame_new(0);
          gtk_table_attach_defaults(GTK_TABLE(scan_button_table), info_frame, 0, 1, 0, 1);
          gtk_frame_set_shadow_type(GTK_FRAME(info_frame), GTK_SHADOW_IN);
          gtk_widget_show(info_frame);

          {
            GtkWidget *info_box;

            info_box = gtk_hbox_new(FALSE, 0);
            gtk_container_add(GTK_CONTAINER(info_frame), info_box);
            gtk_widget_show(info_box);

            {
              xsane.info_label = gtk_label_new(TEXT_INFO_BOX);
              gtk_box_pack_start(GTK_BOX(info_box), xsane.info_label, TRUE, TRUE, 2);
              gtk_widget_show(xsane.info_label);
            }
          }
        }


        /* progress bar */
        {
          xsane.progress_bar = (GtkProgressBar *) gtk_progress_bar_new();
          gtk_table_attach_defaults(GTK_TABLE(scan_button_table), GTK_WIDGET(xsane.progress_bar), 0, 1, 1, 2);
          gtk_progress_set_show_text(GTK_PROGRESS(xsane.progress_bar), TRUE);
          gtk_progress_set_format_string(GTK_PROGRESS(xsane.progress_bar), "");
          gtk_widget_show(GTK_WIDGET(xsane.progress_bar));
        }


        /* The Scan button */
        {
          xsane.start_button = gtk_button_new_with_label(BUTTON_SCAN);
          gtk_table_attach_defaults(GTK_TABLE(scan_button_table), xsane.start_button, 1, 2, 0, 1);
          xsane_back_gtk_set_tooltip(xsane.tooltips, xsane.start_button, DESC_SCAN_START);
          gtk_widget_add_accelerator(xsane.start_button, "clicked", xsane.accelerator_group, GDK_Return, GDK_CONTROL_MASK, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
          g_signal_connect(GTK_OBJECT(xsane.start_button), "clicked", (GtkSignalFunc) xsane_scan_callback, NULL);
          gtk_widget_show(xsane.start_button);
        }

        /* The Cancel button */
        {
#ifdef HAVE_GTK2
          xsane.cancel_button = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
#else
          xsane.cancel_button = gtk_button_new_with_label(BUTTON_CANCEL);
#endif
          gtk_table_attach_defaults(GTK_TABLE(scan_button_table), xsane.cancel_button, 1, 2, 1, 2);
          xsane_back_gtk_set_tooltip(xsane.tooltips, xsane.cancel_button, DESC_SCAN_CANCEL);
          gtk_widget_add_accelerator(xsane.cancel_button, "clicked", xsane.accelerator_group, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)(GTK_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
          gtk_widget_set_sensitive(xsane.cancel_button, FALSE); 
          gtk_widget_show(xsane.cancel_button);
        }
      }
    }
  }

  return main_window_left_pane;
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_histogram_ignore_border_callback(GtkWidget *widget, gpointer data)
{
  DBG(DBG_proc, "xsane_histogram_ignore_border_callback\n");
 
  if (xsane.preview)
    preview_draw_selection_rect(xsane.preview);

  preferences.histogram_ignore_border = gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) * 5;

  if (xsane.always_auto_enhance)
    xsane_auto_enhance();
  else
    xsane_enhancement_by_histogram(TRUE);

  //if (xsane.preview)
    //preview_draw_selection_rect(xsane.preview);
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_histogram_clipping_margin_callback(GtkWidget *widget, gpointer data)
{
  DBG(DBG_proc, "xsane_histogram_clipping_margin_callback\n");
 
  preferences.histogram_clipping_margin = (gtk_combo_box_get_active(GTK_COMBO_BOX(widget)) - 3) * 5;

  if (xsane.always_auto_enhance)
    xsane_auto_enhance();
  else
    xsane_enhancement_by_histogram(TRUE);
}

/* ---------------------------------------------------------------------------------------------------------------------- */

GtkWidget *xsane_build_main_window_right_pane()
{
  GtkWidget *main_window_right_pane;

  DBG(DBG_proc, "xsane_build_main_window_right_pane\n");

  main_window_right_pane = gtk_scrolled_window_new(NULL, NULL);
  gtk_widget_show(main_window_right_pane);
  gtk_widget_set_size_request(main_window_right_pane, 350, -1);
  gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(main_window_right_pane),
                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

  {
    xsane.main_window_right_pane_vbox = gtk_vbox_new(FALSE, 0);
    gtk_widget_show(xsane.main_window_right_pane_vbox);
    gtk_container_set_border_width(GTK_CONTAINER(xsane.main_window_right_pane_vbox), 5);
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(main_window_right_pane), xsane.main_window_right_pane_vbox);

    /* histograms under xsane_histograms_expander */
    {
      GtkWidget *xsane_histograms_expander;

      xsane_histograms_expander = gtk_expander_new(EXPANDER_HISTOGRAM);
      gtk_box_pack_start(GTK_BOX(xsane.main_window_right_pane_vbox), xsane_histograms_expander, FALSE, FALSE, 0);
      gtk_widget_show(xsane_histograms_expander);
      g_signal_connect(GTK_OBJECT(xsane_histograms_expander), "activate", (GtkSignalFunc) xsane_show_histogram_callback, (void *) 0);
      gtk_expander_set_expanded(GTK_EXPANDER(xsane_histograms_expander), preferences.show_histogram);

      {
        GtkWidget *xsane_histograms_vbox;  

        xsane_histograms_vbox = gtk_vbox_new(FALSE, 0);
        gtk_container_add(GTK_CONTAINER(xsane_histograms_expander), xsane_histograms_vbox);
        gtk_widget_show(xsane_histograms_vbox);

        /* add histogram images and sliders */

        xsane_create_histogram(xsane_histograms_vbox, FRAME_RAW_IMAGE, 256, 100, &(xsane.histogram_raw));

        xsane_separator_new(xsane_histograms_vbox, 0);

        /* sliders */
        {
          xsane.slider_gray.r = 1;
          xsane.slider_gray.g = 1;
          xsane.slider_gray.b = 1;
          xsane.slider_gray.active = XSANE_SLIDER_ACTIVE;
          xsane_create_slider(&xsane.slider_gray);
          gtk_box_pack_start(GTK_BOX(xsane_histograms_vbox), xsane.slider_gray.preview, FALSE, FALSE, 0);
          gtk_widget_show(xsane.slider_gray.preview);
          //gtk_widget_realize(xsane.slider_gray.preview);

          //xsane_separator_new(xsane_histograms_vbox, 0);

          xsane.slider_red.r = 1;
          xsane.slider_red.g = 0;
          xsane.slider_red.b = 0;
          xsane.slider_red.active = XSANE_SLIDER_ACTIVE;
          xsane_create_slider(&xsane.slider_red);
          gtk_box_pack_start(GTK_BOX(xsane_histograms_vbox), xsane.slider_red.preview, FALSE, FALSE, 0);
          gtk_widget_show(xsane.slider_red.preview);
          //gtk_widget_realize(xsane.slider_red.preview);

          //xsane_separator_new(xsane_histograms_vbox, 0);

          xsane.slider_green.r = 0;
          xsane.slider_green.g = 1;
          xsane.slider_green.b = 0;
          xsane.slider_green.active = XSANE_SLIDER_ACTIVE;
          xsane_create_slider(&xsane.slider_green);
          gtk_box_pack_start(GTK_BOX(xsane_histograms_vbox), xsane.slider_green.preview, FALSE, FALSE, 0);
          gtk_widget_show(xsane.slider_green.preview);
          //gtk_widget_realize(xsane.slider_green.preview);

          //xsane_separator_new(xsane_histograms_vbox, 0);

          xsane.slider_blue.r = 0;
          xsane.slider_blue.g = 0;
          xsane.slider_blue.b = 1;
          xsane.slider_blue.active = XSANE_SLIDER_ACTIVE;
          xsane_create_slider(&xsane.slider_blue);
          gtk_box_pack_start(GTK_BOX(xsane_histograms_vbox), xsane.slider_blue.preview, FALSE, FALSE, 0);
          gtk_widget_show(xsane.slider_blue.preview);
          //gtk_widget_realize(xsane.slider_blue.preview);

          xsane_draw_slider_level(&xsane.slider_gray);
          xsane_draw_slider_level(&xsane.slider_red);
          xsane_draw_slider_level(&xsane.slider_green);
          xsane_draw_slider_level(&xsane.slider_blue);
        }

        xsane_separator_new(xsane_histograms_vbox, 0);           

        /* Enhanced histogram */

        xsane_create_histogram(xsane_histograms_vbox, FRAME_ENHANCED_IMAGE, 256, 100, &(xsane.histogram_enh));

        // color buttons hbox
        {
          GtkWidget *xsane_color_hbox;

          xsane_color_hbox = gtk_hbox_new(TRUE, 5);
          gtk_container_add(GTK_CONTAINER(xsane_histograms_vbox), xsane_color_hbox);
          gtk_container_set_border_width(GTK_CONTAINER(xsane_color_hbox), 5);
          gtk_widget_show(xsane_color_hbox);

          // color buttons
          {
           GtkWidget *button;  

            button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, xsane_color_hbox, intensity_xpm, DESC_HIST_INTENSITY,
                                                         &xsane.histogram_int,   (void *)xsane_histogram_toggle_button_callback);
            gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_I, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);

            button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, xsane_color_hbox, red_xpm, DESC_HIST_RED,
                                                         &xsane.histogram_red,   (void *)xsane_histogram_toggle_button_callback);
            gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_R, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);

            button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, xsane_color_hbox, green_xpm, DESC_HIST_GREEN,
                                                         &xsane.histogram_green, (void *)xsane_histogram_toggle_button_callback);
            gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_G, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);

            button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, xsane_color_hbox, blue_xpm, DESC_HIST_BLUE,
                                                         &xsane.histogram_blue,  (void *)xsane_histogram_toggle_button_callback);
            gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_B, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);

            button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, xsane_color_hbox, pixel_xpm, DESC_HIST_PIXEL,
                                                         &xsane.histogram_lines, (void *)xsane_histogram_toggle_button_callback);
            gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_M, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);

            button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, xsane_color_hbox, log_xpm, DESC_HIST_LOG,
                                                         &xsane.histogram_log, (void *)xsane_histogram_toggle_button_callback);
            gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_L, GDK_MOD1_MASK, DEF_GTK_ACCEL_LOCKED);
          }
        }

        /* ignore border */
        {
          GtkWidget *hbox;
          GtkWidget *xsane_label;
          GtkWidget *xsane_histogram_ignore_border_combo_box;

          hbox = gtk_hbox_new(FALSE, 5);
          gtk_box_pack_start(GTK_BOX(xsane_histograms_vbox), hbox, FALSE, FALSE, 2);

          xsane_label = gtk_label_new("Ignore Border"); /* opposite order because of box_pack_end */
          gtk_box_pack_start(GTK_BOX(hbox), xsane_label, FALSE, FALSE, 2);
          gtk_widget_show(xsane_label);

          xsane_histogram_ignore_border_combo_box = gtk_combo_box_new_text();
          xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_histogram_ignore_border_combo_box, "Ignore border of selected area");
          gtk_box_pack_end(GTK_BOX(hbox), xsane_histogram_ignore_border_combo_box, TRUE, TRUE, 5);
          gtk_widget_show(xsane_histogram_ignore_border_combo_box);

          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_ignore_border_combo_box), "0%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_ignore_border_combo_box), "5%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_ignore_border_combo_box), "10%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_ignore_border_combo_box), "15%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_ignore_border_combo_box), "20%");

          gtk_combo_box_set_active(GTK_COMBO_BOX(xsane_histogram_ignore_border_combo_box), preferences.histogram_ignore_border/5);
          g_signal_connect(GTK_OBJECT(xsane_histogram_ignore_border_combo_box), "changed", (GtkSignalFunc) xsane_histogram_ignore_border_callback, NULL);

          gtk_widget_show(hbox);
        }

        /* histogram_clipping_margin */
        {
          GtkWidget *hbox;
          GtkWidget *xsane_label;
          GtkWidget *xsane_histogram_clipping_margin_combo_box;

          hbox = gtk_hbox_new(FALSE, 5);
          gtk_box_pack_start(GTK_BOX(xsane_histograms_vbox), hbox, FALSE, FALSE, 2);

          xsane_label = gtk_label_new("Clipping Margin"); /* opposite order because of box_pack_end */
          gtk_box_pack_start(GTK_BOX(hbox), xsane_label, FALSE, FALSE, 2);
          gtk_widget_show(xsane_label);

          xsane_histogram_clipping_margin_combo_box = gtk_combo_box_new_text();
          xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_histogram_clipping_margin_combo_box, "Extra margin for white and black clipping points");
          gtk_box_pack_end(GTK_BOX(hbox), xsane_histogram_clipping_margin_combo_box, TRUE, TRUE, 5);
          gtk_widget_show(xsane_histogram_clipping_margin_combo_box);

          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "-15%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "-10%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "-5%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "0%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "5%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "10%");
          gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), "15%");

          gtk_combo_box_set_active(GTK_COMBO_BOX(xsane_histogram_clipping_margin_combo_box), preferences.histogram_clipping_margin/5+3);
          g_signal_connect(GTK_OBJECT(xsane_histogram_clipping_margin_combo_box), "changed", (GtkSignalFunc) xsane_histogram_clipping_margin_callback, NULL);

          gtk_widget_show(hbox);
        }
      }
    }

    xsane_create_basic_adjustment_tools();
    gtk_box_pack_start(GTK_BOX(xsane.main_window_right_pane_vbox), xsane.basic_adjustments.container, FALSE, FALSE, 0);
  }

  return main_window_right_pane;
}

/* ---------------------------------------------------------------------------------------------------------------------- */

/* IMAGE_TYPE */
void xsane_save_image_type_callback(GtkWidget *widget, gpointer data)
{
  DBG(DBG_proc, "xsane_save_image_type_callback\n");
 
  preferences.save_image_type = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_create_scan_mode_medium_box() /* creates the XSane option window */
{
 GtkWidget *hbox;
 GtkWidget *xsane_vbox;
 GtkWidget *xsane_modus_menu;
 GtkWidget *xsane_modus_item;
 GtkWidget *xsane_modus_option_menu;
 GtkWidget *xsane_vbox_xsane_modus;
 GtkWidget *xsane_spinbutton;
 GtkWidget *xsane_medium_option_menu, *xsane_medium_menu, *xsane_medium_item;
 GtkWidget *pixmapwidget;
 GdkBitmap *mask;
 GdkPixmap *pixmap;
 GtkObject *adjustment;
 int i;

  DBG(DBG_proc, "xsane_create_scan_mode_medium_box\n");

  /* xsane main options */

  xsane.scan_mode_medium.body = gtk_hbox_new(FALSE, 2);
  gtk_widget_show(xsane.scan_mode_medium.body);
  xsane_vbox = gtk_vbox_new(/* homogeneous */ FALSE, 0);
  gtk_widget_show(xsane_vbox);
/*  gtk_box_pack_start(GTK_BOX(xsane.scan_mode_medium.body), xsane_vbox, FALSE, FALSE, 0); */ /* make scales fixed */
  gtk_box_pack_start(GTK_BOX(xsane.scan_mode_medium.body), xsane_vbox, TRUE, TRUE, 0); /* make scales sizeable */

  xsane_vbox_xsane_modus = gtk_vbox_new(FALSE, 2);
  gtk_box_pack_start(GTK_BOX(xsane_vbox), xsane_vbox_xsane_modus, TRUE, TRUE, 0); /* sizeable framehight */
  gtk_widget_show(xsane_vbox_xsane_modus);

  /* ADF pages selection */
  hbox = gtk_hbox_new(FALSE, 5);
  gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), hbox, FALSE, FALSE, 2);
  gtk_widget_show(hbox);

  pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) adf_xpm);
  pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
  gtk_box_pack_start(GTK_BOX(hbox), pixmapwidget, FALSE, FALSE, 2);
  gdk_drawable_unref(pixmap);
  gdk_drawable_unref(mask);
  gtk_widget_show(pixmapwidget);

  /* adf pages maximum */
  adjustment = gtk_adjustment_new(preferences.adf_pages_max, 1, 9999, 1, 10, 0);
  xsane_spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 0, 0);
  gtk_widget_set_name(GTK_WIDGET(xsane_spinbutton), XSANE_WIDGET_NAME_SPINBUTTON);

  gtk_widget_set_size_request(xsane_spinbutton, 55, -1);
  gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(xsane_spinbutton), FALSE);
  xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_spinbutton, DESC_ADF_PAGES_MAX);
  g_signal_connect(GTK_OBJECT(xsane_spinbutton), "changed", (GtkSignalFunc) xsane_adf_pages_max_callback, NULL);
  xsane.adf_pages_max_entry = xsane_spinbutton;
  gtk_box_pack_start(GTK_BOX(hbox), xsane_spinbutton, FALSE, FALSE, 5);
  gtk_widget_show(xsane_spinbutton);

  {
    xsane.scan_mode_medium.mode_widget = gtk_hbox_new(FALSE, 0);
    gtk_box_pack_end(GTK_BOX(hbox), xsane.scan_mode_medium.mode_widget, FALSE, FALSE, 0);

    xsane_modus_menu = gtk_menu_new();
    gtk_menu_set_accel_group(GTK_MENU(xsane_modus_menu), xsane.accelerator_group);

    xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_VIEWER);
    gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_V, GDK_CONTROL_MASK, (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
    gtk_widget_set_size_request(xsane_modus_item, 60, -1);
    gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item);
    g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_VIEWER]);
    gtk_widget_show(xsane_modus_item);

    xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_SAVE);
    gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_S, GDK_CONTROL_MASK, (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
    gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item);
    g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_SAVE]);
    gtk_widget_show(xsane_modus_item);

    xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_COPY);
    gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_C, GDK_CONTROL_MASK, (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
    gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item);
    g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_COPY]);
    gtk_widget_show(xsane_modus_item);

    xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_MULTIPAGE);
    gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_M, GDK_CONTROL_MASK, (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
    gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item);
    g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_MULTIPAGE]);
    gtk_widget_show(xsane_modus_item);

    xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_FAX);
    gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_F, GDK_CONTROL_MASK, (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
    gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item);
    g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_FAX]);
    gtk_widget_show(xsane_modus_item);

#ifdef XSANE_ACTIVATE_EMAIL
    xsane_modus_item = gtk_menu_item_new_with_label(MENU_ITEM_EMAIL);
    gtk_widget_add_accelerator(xsane_modus_item, "activate", xsane.accelerator_group, GDK_E, GDK_CONTROL_MASK, (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
    gtk_container_add(GTK_CONTAINER(xsane_modus_menu), xsane_modus_item);
    g_signal_connect(GTK_OBJECT(xsane_modus_item), "activate", (GtkSignalFunc) xsane_modus_callback, &xsane_scanmode_number[XSANE_EMAIL]);
    gtk_widget_show(xsane_modus_item);
#endif

    xsane_modus_option_menu = gtk_option_menu_new();
    xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_modus_option_menu, DESC_XSANE_MODE);
    gtk_box_pack_end(GTK_BOX(xsane.scan_mode_medium.mode_widget), xsane_modus_option_menu, FALSE, FALSE, 5);
    gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_modus_option_menu), xsane_modus_menu);
    gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_modus_option_menu), xsane.xsane_mode);
    gtk_widget_show(xsane_modus_option_menu);

    pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) target_xpm); /* XSANE_MODE */
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gtk_box_pack_end(GTK_BOX(xsane.scan_mode_medium.mode_widget), pixmapwidget, FALSE, FALSE, 2);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);
    gtk_widget_show(pixmapwidget);

    xsane.xsanemode_widget = xsane_modus_option_menu;
  }


  /* save / viewer */
  {
    GtkWidget *save_viewer_widget;

    save_viewer_widget = gtk_vbox_new(FALSE, 0);
    gtk_widget_show(save_viewer_widget);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), save_viewer_widget, FALSE, FALSE, 2);

    xsane.scan_mode_medium.save_viewer_widget = save_viewer_widget;

    xsane.copy_number_entry = NULL;

    if ( (xsane.mode == XSANE_STANDALONE) && (!xsane.force_filename) )
    {
      xsane_outputfilename_new(save_viewer_widget); /* create filename box, step and type menu */

      /* IMAGE_TYPE: Save image as Normal, Inverted, RAW */
      {
        GtkWidget *xsane_label;
        GtkWidget *xsane_save_image_type_combo_box;

        hbox = gtk_hbox_new(FALSE, 5);
        gtk_box_pack_start(GTK_BOX(save_viewer_widget), hbox, FALSE, FALSE, 2);

        xsane_label = gtk_label_new("Save image as");
        gtk_box_pack_start(GTK_BOX(hbox), xsane_label, FALSE, FALSE, 2);
        gtk_widget_show(xsane_label);

        xsane_save_image_type_combo_box = gtk_combo_box_new_text();
        xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_save_image_type_combo_box, "Save image as Normal, Inverted, or RAW");
        gtk_box_pack_end(GTK_BOX(hbox), xsane_save_image_type_combo_box, TRUE, TRUE, 5);
        gtk_widget_show(xsane_save_image_type_combo_box);

        gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_save_image_type_combo_box), "Normal");
        gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_save_image_type_combo_box), "Inverted");
        gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_save_image_type_combo_box), "Raw");

        gtk_combo_box_set_active(GTK_COMBO_BOX(xsane_save_image_type_combo_box), preferences.save_image_type);
        g_signal_connect(GTK_OBJECT(xsane_save_image_type_combo_box), "changed", (GtkSignalFunc) xsane_save_image_type_callback, NULL);

        gtk_widget_show(hbox);
      }
    }
  }

  /* copy widget */
  {
    GtkWidget *copy_widget;
    GtkWidget *xsane_printer_option_menu, *xsane_printer_menu, *xsane_printer_item;
    GtkWidget *paper_orientation_option_menu, *paper_orientation_menu, *paper_orientation_item;

    copy_widget = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), copy_widget, FALSE, FALSE, 2);

    xsane.scan_mode_medium.copy_widget = copy_widget;

    pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) printer_xpm);
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gtk_box_pack_start(GTK_BOX(copy_widget), pixmapwidget, FALSE, FALSE, 2);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);
    gtk_widget_show(pixmapwidget);


    /* number of copies */
    adjustment = gtk_adjustment_new(xsane.copy_number, 1, 99, 1, 10, 0);
    xsane_spinbutton = gtk_spin_button_new(GTK_ADJUSTMENT(adjustment), 0, 0);
    gtk_widget_set_name(GTK_WIDGET(xsane_spinbutton), XSANE_WIDGET_NAME_SPINBUTTON);

    gtk_widget_set_size_request(xsane_spinbutton, 40, -1);
    gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(xsane_spinbutton), FALSE);
    xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_spinbutton, DESC_COPY_NUMBER);
    xsane.copy_number_entry = xsane_spinbutton;
    gtk_box_pack_start(GTK_BOX(copy_widget), xsane_spinbutton, FALSE, FALSE, 5);
    gtk_widget_show(xsane_spinbutton);


    /* printer position */
    paper_orientation_menu = gtk_menu_new();

    for (i = 0; i <= 12; ++i)
    {
     gchar **xpm_d;

      if (i == 5) /* 5, 6, 7 are not used */
      {
        i = 8;
      }

      switch (i)
      {
        /* portrait */
        default:
        case 0:
           xpm_d = (gchar **) paper_orientation_portrait_top_left_xpm;
         break;

        case 1:
           xpm_d = (gchar **) paper_orientation_portrait_top_right_xpm;
         break;

        case 2:
           xpm_d = (gchar **) paper_orientation_portrait_bottom_right_xpm;
         break;

        case 3:
           xpm_d = (gchar **) paper_orientation_portrait_bottom_left_xpm;
         break;

        case 4:
           xpm_d = (gchar **) paper_orientation_portrait_center_xpm;
         break;

        /* landscape */
        case 8:
           xpm_d = (gchar **) paper_orientation_landscape_top_left_xpm;
         break;

        case 9:
           xpm_d = (gchar **) paper_orientation_landscape_top_right_xpm;
         break;

        case 10:
           xpm_d = (gchar **) paper_orientation_landscape_bottom_right_xpm;
         break;

        case 11:
           xpm_d = (gchar **) paper_orientation_landscape_bottom_left_xpm;
         break;

        case 12:
           xpm_d = (gchar **) paper_orientation_landscape_center_xpm;
         break;
      }

      paper_orientation_item = gtk_menu_item_new();
      pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, xpm_d);
      pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
      gtk_container_add(GTK_CONTAINER(paper_orientation_item), pixmapwidget);
      gtk_widget_show(pixmapwidget);
      gdk_drawable_unref(pixmap);
      gdk_drawable_unref(mask);


      gtk_container_add(GTK_CONTAINER(paper_orientation_menu), paper_orientation_item);
      g_signal_connect(GTK_OBJECT(paper_orientation_item), "activate", (GtkSignalFunc) xsane_paper_orientation_callback, (void *) (long)i);

      gtk_widget_show(paper_orientation_item);
    }

    paper_orientation_option_menu = gtk_option_menu_new();
    xsane_back_gtk_set_tooltip(xsane.tooltips, paper_orientation_option_menu, DESC_PAPER_ORIENTATION);
    gtk_box_pack_end(GTK_BOX(copy_widget), paper_orientation_option_menu, FALSE, FALSE, 5);
    gtk_option_menu_set_menu(GTK_OPTION_MENU(paper_orientation_option_menu), paper_orientation_menu);

    /* set default selection */
    if (preferences.paper_orientation < 8) /* portrai number is correct */
    {
      gtk_option_menu_set_history(GTK_OPTION_MENU(paper_orientation_option_menu), preferences.paper_orientation);
    }
    else /* numbers 5, 6, 7 are unused, so we have to substract 3 for landscape mode */
    {
      gtk_option_menu_set_history(GTK_OPTION_MENU(paper_orientation_option_menu), preferences.paper_orientation-3);
    }

    gtk_widget_show(paper_orientation_option_menu);


    xsane_printer_menu = gtk_menu_new();

    for (i=0; i < preferences.printerdefinitions; i++)
    {
      xsane_printer_item = gtk_menu_item_new_with_label(preferences.printer[i]->name);
      if (i<12)
      {
        gtk_widget_add_accelerator(xsane_printer_item, "activate", xsane.accelerator_group,
                                   GDK_F1+i, GDK_SHIFT_MASK,  (GtkAccelFlags)(DEF_GTK_MENU_ACCEL_VISIBLE | DEF_GTK_ACCEL_LOCKED));
      }
      gtk_container_add(GTK_CONTAINER(xsane_printer_menu), xsane_printer_item);
      g_signal_connect(GTK_OBJECT(xsane_printer_item), "activate", (GtkSignalFunc) xsane_printer_callback, (void *) (long)i);
      gtk_widget_show(xsane_printer_item);
    }

    xsane_printer_option_menu = gtk_option_menu_new();
    xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_printer_option_menu, DESC_PRINTER_SELECT);
    gtk_box_pack_end(GTK_BOX(copy_widget), xsane_printer_option_menu, FALSE, FALSE, 2);
    gtk_widget_show(xsane_printer_option_menu);
    gtk_widget_show(copy_widget);

    gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_printer_option_menu), xsane_printer_menu);
    gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_printer_option_menu), preferences.printernr);
  }

#ifdef HAVE_LIBLCMS
  {
    GtkWidget *cms_widget;

    cms_widget = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), cms_widget, FALSE, FALSE, 2);

    xsane.scan_mode_medium.cms_widget = cms_widget;

    pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) cms_xpm);
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gtk_box_pack_start(GTK_BOX(cms_widget), pixmapwidget, FALSE, FALSE, 2);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);
    gtk_widget_show(pixmapwidget);

    xsane.cms_function_option_menu = xsane_back_gtk_cms_function_menu_new(preferences.cms_function, (GtkSignalFunc) xsane_cms_function_menu_callback);
    gtk_box_pack_end(GTK_BOX(cms_widget), xsane.cms_function_option_menu, TRUE, TRUE, 5);
    gtk_widget_show(xsane.cms_function_option_menu);
  }
#endif

  xsane_separator_new(xsane_vbox_xsane_modus, 2);

  /* scan source */
  {
    GtkWidget *scansource_widget_container;

    scansource_widget_container = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), scansource_widget_container, FALSE, FALSE, 0);
    gtk_widget_show(scansource_widget_container);

    xsane.scan_mode_medium.scansource_widget_container = scansource_widget_container;
    xsane.scan_mode_medium.scansource_widget_body = NULL;
  }

  /* scanmode */
  {
    GtkWidget *scanmode_widget_container;

    scanmode_widget_container = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), scanmode_widget_container, FALSE, FALSE, 0);
    gtk_widget_show(scanmode_widget_container);

    xsane.scan_mode_medium.scanmode_widget_container = scanmode_widget_container;
    xsane.scan_mode_medium.scanmode_widget_body = NULL;
  }

  /* bit depth */
  {
    GtkWidget *bitdepth_widget_container;

    bitdepth_widget_container = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), bitdepth_widget_container, FALSE, FALSE, 0);
    gtk_widget_show(bitdepth_widget_container);

    xsane.scan_mode_medium.bitdepth_widget_container = bitdepth_widget_container;
    xsane.scan_mode_medium.bitdepth_widget_body = NULL;
  }

  /* medium selection */
  {
    GtkWidget *medium_widget;

    medium_widget = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), medium_widget, FALSE, FALSE, 2);

    xsane.scan_mode_medium.medium_widget = medium_widget;

    if (xsane.medium_calibration)
    {
      pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) medium_edit_xpm);
    }
    else
    {
      pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) medium_xpm);
    }
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gtk_box_pack_start(GTK_BOX(medium_widget), pixmapwidget, FALSE, FALSE, 2);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);
    gtk_widget_show(pixmapwidget);

    xsane_medium_menu = gtk_menu_new();

    for (i=0; i<preferences.medium_definitions; i++)
    {
      xsane_medium_item = gtk_menu_item_new_with_label(preferences.medium[i]->name);
      gtk_menu_append(GTK_MENU(xsane_medium_menu), xsane_medium_item);
      g_signal_connect(GTK_OBJECT(xsane_medium_item), "button_press_event", (GtkSignalFunc) xsane_medium_context_menu_callback, (void *) (long)i);
      g_signal_connect(GTK_OBJECT(xsane_medium_item), "activate", (GtkSignalFunc) xsane_set_medium_callback, (void *) (long)i);
      gtk_object_set_data(GTK_OBJECT(xsane_medium_item), "Selection", (void *) (long)i);

      gtk_widget_show(xsane_medium_item);
    }

    gtk_widget_show(xsane_medium_menu);

    xsane_medium_option_menu = gtk_option_menu_new();
    xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_medium_option_menu, DESC_XSANE_MEDIUM);
    gtk_box_pack_end(GTK_BOX(medium_widget), xsane_medium_option_menu, TRUE, TRUE, 5);
    gtk_option_menu_set_menu(GTK_OPTION_MENU(xsane_medium_option_menu), xsane_medium_menu);
    gtk_option_menu_set_history(GTK_OPTION_MENU(xsane_medium_option_menu), preferences.medium_nr);
    gtk_widget_show(xsane_medium_option_menu);
    xsane.medium_widget = xsane_medium_option_menu;

    if (xsane.medium_calibration) /* are we running in medium calibration mode? */
    {
      xsane_apply_medium_definition_as_enhancement(preferences.medium[preferences.medium_nr]);
      xsane_set_medium(NULL);
    }
    else
    {
      xsane_set_medium(preferences.medium[preferences.medium_nr]);
    }
  }

  /* resolution */
  {
    GtkWidget *resolution_widget_container;

    resolution_widget_container = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), resolution_widget_container, FALSE, FALSE, 0);
    gtk_widget_show(resolution_widget_container);

    xsane.scan_mode_medium.resolution_widget_container = resolution_widget_container;
    xsane.scan_mode_medium.resolution_widget_body = NULL;
  }

  /*
     geometry
  xsane.device_options.well_known.coord[xsane_back_gtk_TL_X]
  xsane.device_options.well_known.coord[xsane_back_gtk_TL_Y]
  xsane.device_options.well_known.coord[xsane_back_gtk_BR_X]
  xsane.device_options.well_known.coord[xsane_back_gtk_BR_Y]
  */

  xsane_separator_new(xsane_vbox_xsane_modus, 2);

  /* coord */
  {
    GtkWidget *coord_widget_container;

    coord_widget_container = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(xsane_vbox_xsane_modus), coord_widget_container, FALSE, FALSE, 0);
    gtk_widget_show(coord_widget_container);

    xsane.scan_mode_medium.coord_widget_container = coord_widget_container;
    xsane.scan_mode_medium.coord_widget_body[0] = NULL;
    xsane.scan_mode_medium.coord_widget_body[1] = NULL;
    xsane.scan_mode_medium.coord_widget_body[2] = NULL;
    xsane.scan_mode_medium.coord_widget_body[3] = NULL;
  }

  xsane_update_histogram(TRUE /* update raw */);
  xsane_update_gamma_dialog();
}

void xsane_update_scan_mode_medium_box() /* creates the XSane option window */
{
 const SANE_Option_Descriptor *opt;

  DBG(DBG_proc, "xsane_update_scan_mode_medium_box\n");
printf( "xsane_update_scan_mode_medium_box\n");

  /* scan copy fax selection, in hbox of ADF pages */
  if ( (xsane.mode == XSANE_STANDALONE) && (xsane.mode_selection) ) /* display xsane mode selection menu */
  {
    gtk_widget_show(xsane.scan_mode_medium.mode_widget);
  }
  else
  {
    gtk_widget_hide(xsane.scan_mode_medium.mode_widget);
  }

  gtk_widget_hide(xsane.scan_mode_medium.save_viewer_widget);
  gtk_widget_hide(xsane.scan_mode_medium.copy_widget);
  if ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) )
  {
    gtk_widget_show(xsane.scan_mode_medium.save_viewer_widget);
  }
  else if (xsane.xsane_mode == XSANE_COPY)
  {
    gtk_widget_show(xsane.scan_mode_medium.copy_widget);
  }

#ifdef HAVE_LIBLCMS
  if ((xsane.enable_color_management) && 
      ( (xsane.xsane_mode == XSANE_VIEWER) ||
        (xsane.xsane_mode == XSANE_SAVE) ||
        (xsane.xsane_mode == XSANE_EMAIL) ||
        (xsane.xsane_mode == XSANE_MULTIPAGE)
      )
     )
  {
    gtk_widget_show(xsane.scan_mode_medium.cms_widget);
  }
  else
  {
    gtk_widget_hide(xsane.scan_mode_medium.cms_widget);
  }
#endif

  /* input selection */
  opt = xsane_get_option_descriptor(xsane.device_options.dev, xsane.device_options.well_known.scansource);
  if (opt != NULL && SANE_OPTION_IS_ACTIVE(opt->cap))
  {
    GtkWidget *scansource_widget_container = xsane.scan_mode_medium.scansource_widget_container;
    GtkWidget *scansource_widget_body = xsane.scan_mode_medium.scansource_widget_body;
    GtkWidget *pixmapwidget;
    GdkPixmap *pixmap;
    GdkBitmap *mask;

    if (scansource_widget_body != NULL)
      gtk_widget_destroy(scansource_widget_body);

    scansource_widget_body = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(scansource_widget_container), scansource_widget_body, FALSE, FALSE, 2);

    xsane.scan_mode_medium.scansource_widget_body = scansource_widget_body;

    pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) scanner_xpm);
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);

    if (xsane_build_device_option_widget(xsane.device_options.well_known.scansource, scansource_widget_body, pixmapwidget))
      gtk_widget_show(scansource_widget_body);
  }
  else
  {
    gtk_widget_hide(xsane.scan_mode_medium.scansource_widget_body);
  }

  /* scanmode */
  opt = xsane_get_option_descriptor(xsane.device_options.dev, xsane.device_options.well_known.scanmode);
  if (opt != NULL && SANE_OPTION_IS_ACTIVE(opt->cap))
  {
    GtkWidget *scanmode_widget_container = xsane.scan_mode_medium.scanmode_widget_container;
    GtkWidget *scanmode_widget_body = xsane.scan_mode_medium.scanmode_widget_body;
    GtkWidget *pixmapwidget;
    GdkPixmap *pixmap;
    GdkBitmap *mask;

    if (scanmode_widget_body != NULL)
      gtk_widget_destroy(scanmode_widget_body);

    scanmode_widget_body = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(scanmode_widget_container), scanmode_widget_body, FALSE, FALSE, 2);

    xsane.scan_mode_medium.scanmode_widget_body = scanmode_widget_body;

    pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) colormode_xpm);
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);

    if (xsane_build_device_option_widget(xsane.device_options.well_known.scanmode, scanmode_widget_body, pixmapwidget))
      gtk_widget_show(scanmode_widget_body);
  }
  else
  {
    gtk_widget_hide(xsane.scan_mode_medium.scanmode_widget_body);
  }

  opt = xsane_get_option_descriptor(xsane.device_options.dev, xsane.device_options.well_known.bit_depth);
  if (opt != NULL && SANE_OPTION_IS_ACTIVE(opt->cap))
  {
    GtkWidget *bitdepth_widget_container = xsane.scan_mode_medium.bitdepth_widget_container;
    GtkWidget *bitdepth_widget_body = xsane.scan_mode_medium.bitdepth_widget_body;
    GtkWidget *pixmapwidget;
    GdkPixmap *pixmap;
    GdkBitmap *mask;

    if (bitdepth_widget_body != NULL)
      gtk_widget_destroy(bitdepth_widget_body);

    bitdepth_widget_body = gtk_hbox_new(FALSE, 5);
    gtk_box_pack_start(GTK_BOX(bitdepth_widget_container), bitdepth_widget_body, FALSE, FALSE, 2);

    xsane.scan_mode_medium.bitdepth_widget_body = bitdepth_widget_body;

    pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, (gchar **) colormode_xpm);
    pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
    gdk_drawable_unref(pixmap);
    gdk_drawable_unref(mask);

    if (xsane_build_device_option_widget(xsane.device_options.well_known.bit_depth, bitdepth_widget_body, pixmapwidget))
      gtk_widget_show(bitdepth_widget_body);
  }
  else
  {
    gtk_widget_hide(xsane.scan_mode_medium.bitdepth_widget_body);
  }

  /* show medium selection when not lineart mode and no color management */
  if ((xsane.param.depth != 1) && (!xsane.enable_color_management))
  {
    gtk_widget_show(xsane.scan_mode_medium.medium_widget);
  }
  else /* no medium selextion for lineart mode: use Full range gamma curve */
  {
    gtk_widget_hide(xsane.scan_mode_medium.medium_widget);
    xsane_set_medium(preferences.medium[0]); /* make sure Full range is active */
  }

  {
    GtkWidget *resolution_widget_container = xsane.scan_mode_medium.resolution_widget_container;
    GtkWidget *resolution_widget_body = xsane.scan_mode_medium.resolution_widget_body;

    if (resolution_widget_body != NULL)
      gtk_widget_destroy(resolution_widget_body);

    resolution_widget_body = gtk_vbox_new(FALSE, 0);
    gtk_box_pack_start(GTK_BOX(resolution_widget_container), resolution_widget_body, FALSE, FALSE, 0);
    gtk_widget_show(resolution_widget_body);

    xsane.scan_mode_medium.resolution_widget_body = resolution_widget_body;

    if ( (xsane.xsane_mode == XSANE_SAVE) || (xsane.xsane_mode == XSANE_VIEWER) )
    {
      /* resolution selection */
      if (!xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi_x, &xsane.resolution_x, resolution_x_xpm,
                                       DESC_RESOLUTION_X, XSANE_GTK_NAME_X_RESOLUTION)) /* draw x resolution widget if possible */
      {
        xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi_y, &xsane.resolution_y, resolution_y_xpm,
                                    DESC_RESOLUTION_Y, XSANE_GTK_NAME_Y_RESOLUTION); /* ok, also draw y resolution widget */
      }
      else /* no x resolution, so lets draw common resolution widget */
      {
        xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi, &xsane.resolution, resolution_xpm,
                                    DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); 
      }
    }
    else if (xsane.xsane_mode == XSANE_COPY)
    {
      xsane_zoom_widget_new(resolution_widget_body);
    }
    else if (xsane.xsane_mode == XSANE_MULTIPAGE)
    {
      xsane.copy_number_entry = NULL;

      /* resolution selection */
      if (!xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi_x, &xsane.resolution_x, resolution_x_xpm,
                                       DESC_RESOLUTION_X, XSANE_GTK_NAME_X_RESOLUTION)) /* draw x resolution widget if possible */
      {
        xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi_y, &xsane.resolution_y, resolution_y_xpm,
                                    DESC_RESOLUTION_Y, XSANE_GTK_NAME_Y_RESOLUTION); /* ok, also draw y resolution widget */
      }
      else /* no x resolution, so lets draw common resolution widget */
      {
        xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi, &xsane.resolution, resolution_xpm,
                                    DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); 
      }

      xsane_multipage_dialog();
    }
    else if (xsane.xsane_mode == XSANE_FAX)
    {
      xsane.copy_number_entry = NULL;

      xsane.resolution   = 204;
      xsane.resolution_x = 204;
      xsane.resolution_y = 196;
      xsane_set_all_resolutions();

      xsane_fax_dialog();
    }
#ifdef XSANE_ACTIVATE_EMAIL
    else if (xsane.xsane_mode == XSANE_EMAIL)
    {
      xsane.copy_number_entry = NULL;

      /* resolution selection */
      if (!xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi_x, &xsane.resolution_x, resolution_x_xpm,
                                       DESC_RESOLUTION_X, XSANE_GTK_NAME_X_RESOLUTION)) /* draw x resolution widget if possible */
      {
        xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi_y, &xsane.resolution_y, resolution_y_xpm,
                                    DESC_RESOLUTION_Y, XSANE_GTK_NAME_Y_RESOLUTION); /* ok, also draw y resolution widget */
      }
      else /* no x resolution, so lets draw common resolution widget */
      {
        xsane_resolution_widget_new(resolution_widget_body, xsane.device_options.well_known.dpi, &xsane.resolution, resolution_xpm,
                                    DESC_RESOLUTION, XSANE_GTK_NAME_RESOLUTION); 
      }

      xsane_email_dialog();
    }
#endif
  }

  {
    gchar **(xpmd[]) = {
      (gchar **) paper_orientation_portrait_top_left_xpm,
      (gchar **) paper_orientation_portrait_top_left_xpm,
      (gchar **) paper_orientation_portrait_bottom_right_xpm,
      (gchar **) paper_orientation_portrait_bottom_right_xpm
    };
    int i;

    GtkWidget *coord_widget_container = xsane.scan_mode_medium.coord_widget_container;
    for (i = 0; i < 4; i++)
    {
      opt = xsane_get_option_descriptor(xsane.device_options.dev, xsane.device_options.well_known.coord[i]);
      if ((opt != NULL) && SANE_OPTION_IS_ACTIVE(opt->cap))
      {
        GtkWidget *coord_widget_body = xsane.scan_mode_medium.coord_widget_body[i];
        GtkWidget *pixmapwidget;
        GdkPixmap *pixmap;
        GdkBitmap *mask;

        if (coord_widget_body != NULL)
          gtk_widget_destroy(coord_widget_body);

        coord_widget_body = gtk_hbox_new(FALSE, 5);
        gtk_box_pack_start(GTK_BOX(coord_widget_container), coord_widget_body, FALSE, FALSE, 2);

        xsane.scan_mode_medium.coord_widget_body[i] = coord_widget_body;

        pixmap = gdk_pixmap_create_from_xpm_d(xsane.main_window->window, &mask, xsane.bg_trans, xpmd[i]);
        pixmapwidget = gtk_image_new_from_pixmap(pixmap, mask);
        gdk_drawable_unref(pixmap);
        gdk_drawable_unref(mask);

        if (xsane_build_device_option_widget(xsane.device_options.well_known.coord[i], coord_widget_body, pixmapwidget))
          gtk_widget_show(coord_widget_body);
      }
    }
  }

printf( "done xsane_update_scan_mode_medium_box\n");
}

/* ---------------------------------------------------------------------------------------------------------------------- */

/* AUTO_ENHANCEMENT_TYPE */
void xsane_enhancement_type_callback(GtkWidget * widget, gpointer data)
{
  xsane.enhancement_type = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));

  if (xsane.always_auto_enhance)
    xsane_auto_enhancement_callback(NULL);
}

/* ---------------------------------------------------------------------------------------------------------------------- */

/* reset free gamma */
void xsane_reset_free_gamma_callback(GtkWidget * widget, gpointer data)
{
  xsane.do_not_reset_free_gamma = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_enhancement_rgb_default_callback(GtkWidget * widget)
{
  DBG(DBG_proc, "xsane_enhancement_rgb_default_callback\n");

  xsane.enhancement_rgb_default = (GTK_TOGGLE_BUTTON(widget)->active != 0);

  if (xsane.enhancement_rgb_default)
  {
    xsane.gamma_red        = 1.0;
    xsane.gamma_green      = 1.0;
    xsane.gamma_blue       = 1.0;

    xsane.brightness_red   = 0.0;
    xsane.brightness_green = 0.0;
    xsane.brightness_blue  = 0.0;

    xsane.contrast_red     = 0.0;
    xsane.contrast_green   = 0.0;
    xsane.contrast_blue    = 0.0;

    xsane.slider_red.value[0] =   0.0;
    xsane.slider_red.value[1] =  50.0;
    xsane.slider_red.value[2] = 100.0;

    xsane.slider_green.value[0] =   0.0;
    xsane.slider_green.value[1] =  50.0;
    xsane.slider_green.value[2] = 100.0;

    xsane.slider_blue.value[0] =   0.0;
    xsane.slider_blue.value[1] =  50.0;
    xsane.slider_blue.value[2] = 100.0;
  }
  else
  {
    xsane.slider_red.value[0] = xsane.slider_gray.value[0];
    xsane.slider_red.value[1] = xsane.slider_gray.value[1];
    xsane.slider_red.value[2] = xsane.slider_gray.value[2];

    xsane.slider_green.value[0] = xsane.slider_gray.value[0];
    xsane.slider_green.value[1] = xsane.slider_gray.value[1];
    xsane.slider_green.value[2] = xsane.slider_gray.value[2];

    xsane.slider_blue.value[0] = xsane.slider_gray.value[0];
    xsane.slider_blue.value[1] = xsane.slider_gray.value[1];
    xsane.slider_blue.value[2] = xsane.slider_gray.value[2];
  }

  xsane_update_sliders();
  xsane_update_gamma_curve(FALSE);
  xsane_refresh_dialog();
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_enhancement_restore()
{
  DBG(DBG_proc, "xsane_enhancement_restore\n");

  xsane.gamma            = preferences.xsane_gamma;
  xsane.gamma_red        = preferences.xsane_gamma_red;
  xsane.gamma_green      = preferences.xsane_gamma_green;
  xsane.gamma_blue       = preferences.xsane_gamma_blue;

  xsane.brightness       = preferences.xsane_brightness;
  xsane.brightness_red   = preferences.xsane_brightness_red;
  xsane.brightness_green = preferences.xsane_brightness_green;
  xsane.brightness_blue  = preferences.xsane_brightness_blue;

  xsane.contrast         = preferences.xsane_contrast;
  xsane.contrast_red     = preferences.xsane_contrast_red;
  xsane.contrast_green   = preferences.xsane_contrast_green;
  xsane.contrast_blue    = preferences.xsane_contrast_blue;

  xsane.enhancement_rgb_default = preferences.xsane_rgb_default;
  xsane.negative                = preferences.xsane_negative;

  xsane_refresh_dialog();
  xsane_enhancement_by_gamma();
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_enhancement_store()
{
  DBG(DBG_proc, "xsane_enhancement_store\n");

  preferences.xsane_gamma            = xsane.gamma;
  preferences.xsane_gamma_red        = xsane.gamma_red;
  preferences.xsane_gamma_green      = xsane.gamma_green;
  preferences.xsane_gamma_blue       = xsane.gamma_blue;

  preferences.xsane_brightness       = xsane.brightness;
  preferences.xsane_brightness_red   = xsane.brightness_red;
  preferences.xsane_brightness_green = xsane.brightness_green;
  preferences.xsane_brightness_blue  = xsane.brightness_blue;

  preferences.xsane_contrast         = xsane.contrast;
  preferences.xsane_contrast_red     = xsane.contrast_red;
  preferences.xsane_contrast_green   = xsane.contrast_green;
  preferences.xsane_contrast_blue    = xsane.contrast_blue;

  preferences.xsane_rgb_default      = xsane.enhancement_rgb_default;
  preferences.xsane_negative         = xsane.negative;
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_enhancement_restore_default()
{
  DBG(DBG_proc, "xsane_enhancement_restore_default\n");

  xsane.gamma            = 1.0;
  xsane.gamma_red        = 1.0;
  xsane.gamma_green      = 1.0;
  xsane.gamma_blue       = 1.0;

  xsane.brightness       = 0.0;
  xsane.brightness_red   = 0.0;
  xsane.brightness_green = 0.0;
  xsane.brightness_blue  = 0.0;

  xsane.contrast         = 0.0;
  xsane.contrast_red     = 0.0;
  xsane.contrast_green   = 0.0;
  xsane.contrast_blue    = 0.0;

  if (! xsane.do_not_reset_free_gamma)
    {
      g_signal_handler_block(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.gray_curve_widget)->curve), xsane.free_gamma.gray_curve_type_changed_handler_id);
      g_signal_handler_block(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.red_curve_widget)->curve), xsane.free_gamma.red_curve_type_changed_handler_id);
      g_signal_handler_block(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.green_curve_widget)->curve), xsane.free_gamma.green_curve_type_changed_handler_id);
      g_signal_handler_block(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.blue_curve_widget)->curve), xsane.free_gamma.blue_curve_type_changed_handler_id);

      xsane_curve_reset(XSANE_CURVE(XSANE_GAMMA_CURVE(xsane.free_gamma.gray_curve_widget)->curve));
      xsane_curve_reset(XSANE_CURVE(XSANE_GAMMA_CURVE(xsane.free_gamma.red_curve_widget)->curve));
      xsane_curve_reset(XSANE_CURVE(XSANE_GAMMA_CURVE(xsane.free_gamma.green_curve_widget)->curve));
      xsane_curve_reset(XSANE_CURVE(XSANE_GAMMA_CURVE(xsane.free_gamma.blue_curve_widget)->curve));

      g_signal_handler_unblock(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.gray_curve_widget)->curve), xsane.free_gamma.gray_curve_type_changed_handler_id);
      g_signal_handler_unblock(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.red_curve_widget)->curve), xsane.free_gamma.red_curve_type_changed_handler_id);
      g_signal_handler_unblock(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.green_curve_widget)->curve), xsane.free_gamma.green_curve_type_changed_handler_id);
      g_signal_handler_unblock(GTK_OBJECT(XSANE_GAMMA_CURVE(xsane.free_gamma.blue_curve_widget)->curve), xsane.free_gamma.blue_curve_type_changed_handler_id);
    }

  xsane_enhancement_by_gamma();
}


/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_create_basic_adjustment_tools()
{
  GtkWidget *container;
  GtkWidget *button;
  GtkWidget *hbox;
  GtkWidget *basic_adj_vbox;

  DBG(DBG_proc, "xsane_create_basic_adjustment_tools\n");

  container = gtk_expander_new(EXPANDER_BASIC);
  gtk_expander_set_expanded(GTK_EXPANDER(container), TRUE);
  gtk_widget_show(container);

  xsane.basic_adjustments.container = container;

  basic_adj_vbox = gtk_vbox_new(FALSE, 2);
  gtk_container_add(GTK_CONTAINER(container), basic_adj_vbox);
  gtk_widget_show(basic_adj_vbox);

  xsane.basic_adjustments.threshold_widget_container
    = xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(basic_adj_vbox), threshold_xpm, DESC_THRESHOLD,
                              xsane.threshold_min, xsane.threshold_max, 1.0, 10.0, 0,
                              &xsane.threshold, &xsane.basic_adjustments.threshold_widget, 0, (void *)xsane_gamma_changed, TRUE);

  // gamma
  {
    xsane.basic_adjustments.gamma_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(basic_adj_vbox), xsane.basic_adjustments.gamma_container);

    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.gamma_container), Gamma_xpm, DESC_GAMMA,
        XSANE_GAMMA_MIN, XSANE_GAMMA_MAX, 0.01, 0.1, 2,
        &xsane.gamma, &xsane.basic_adjustments.gamma_widget, 0, (void *)xsane_gamma_changed, TRUE);

    xsane.basic_adjustments.channel_gamma_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(xsane.basic_adjustments.gamma_container), xsane.basic_adjustments.channel_gamma_container);

    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_gamma_container), Gamma_red_xpm, DESC_GAMMA_R,
        XSANE_GAMMA_MIN, XSANE_GAMMA_MAX, 0.01, 0.1, 2,
        &xsane.gamma_red  , &xsane.basic_adjustments.gamma_red_widget, 0, (void *)xsane_gamma_changed, TRUE);
    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_gamma_container), Gamma_green_xpm, DESC_GAMMA_G,
        XSANE_GAMMA_MIN, XSANE_GAMMA_MAX, 0.01, 0.1, 2,
        &xsane.gamma_green, &xsane.basic_adjustments.gamma_green_widget, 0, (void *)xsane_gamma_changed, TRUE);
    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_gamma_container), Gamma_blue_xpm, DESC_GAMMA_B,
        XSANE_GAMMA_MIN, XSANE_GAMMA_MAX, 0.01, 0.1, 2,
        &xsane.gamma_blue , &xsane.basic_adjustments.gamma_blue_widget, 0, (void *)xsane_gamma_changed, TRUE);

    xsane_separator_new(xsane.basic_adjustments.channel_gamma_container, 2);
  }

  // brightness
  {
    xsane.basic_adjustments.brightness_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(basic_adj_vbox), xsane.basic_adjustments.brightness_container);

    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.brightness_container), brightness_xpm, DESC_BRIGHTNESS,
        xsane.brightness_min, xsane.brightness_max, 0.1, 1.0, 1,
        &xsane.brightness, &xsane.basic_adjustments.brightness_widget, 0, (void *)xsane_gamma_changed, TRUE);

    xsane.basic_adjustments.channel_brightness_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(xsane.basic_adjustments.brightness_container), xsane.basic_adjustments.channel_brightness_container);

    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_brightness_container), brightness_red_xpm, DESC_BRIGHTNESS_R,
        xsane.brightness_min, xsane.brightness_max, 0.1, 1.0, 1,
        &xsane.brightness_red  , &xsane.basic_adjustments.brightness_red_widget, 0, (void *)xsane_gamma_changed, TRUE);
    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_brightness_container), brightness_green_xpm, DESC_BRIGHTNESS_G,
        xsane.brightness_min, xsane.brightness_max, 0.1, 1.0, 1,
        &xsane.brightness_green, &xsane.basic_adjustments.brightness_green_widget, 0, (void *)xsane_gamma_changed, TRUE);
    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_brightness_container), brightness_blue_xpm, DESC_BRIGHTNESS_B,
        xsane.brightness_min, xsane.brightness_max, 0.1, 1.0, 1,
        &xsane.brightness_blue,  &xsane.basic_adjustments.brightness_blue_widget, 0, (void *)xsane_gamma_changed, TRUE);

    xsane_separator_new(xsane.basic_adjustments.channel_brightness_container, 2);
  }

  // contrast
  {
    xsane.basic_adjustments.contrast_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(basic_adj_vbox), xsane.basic_adjustments.contrast_container);

    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.contrast_container), contrast_xpm, DESC_CONTRAST,
        xsane.contrast_gray_min, xsane.contrast_max, 0.1, 1.0, 1,
        &xsane.contrast, &xsane.basic_adjustments.contrast_widget, 0, (void *)xsane_gamma_changed, TRUE);

    xsane.basic_adjustments.channel_contrast_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(xsane.basic_adjustments.contrast_container), xsane.basic_adjustments.channel_contrast_container);

    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_contrast_container), contrast_red_xpm, DESC_CONTRAST_R,
                                xsane.contrast_min, xsane.contrast_max, 0.1, 1.0, 1,
                                &xsane.contrast_red  , &xsane.basic_adjustments.contrast_red_widget, 0, (void *)xsane_gamma_changed, TRUE);
    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_contrast_container), contrast_green_xpm, DESC_CONTRAST_G,
                                xsane.contrast_min, xsane.contrast_max, 0.1, 1.0, 1,
                                &xsane.contrast_green, &xsane.basic_adjustments.contrast_green_widget, 0, (void *)xsane_gamma_changed, TRUE);
    xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(xsane.basic_adjustments.channel_contrast_container), contrast_blue_xpm, DESC_CONTRAST_B,
                                xsane.contrast_min, xsane.contrast_max, 0.1, 1.0, 1,
                                &xsane.contrast_blue,  &xsane.basic_adjustments.contrast_blue_widget, 0, (void *)xsane_gamma_changed, TRUE);
  }


  /* create lower button box (rgb default, negative ,... */
  {
    xsane.basic_adjustments.enhancement_buttons_container = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(basic_adj_vbox), xsane.basic_adjustments.enhancement_buttons_container);

    hbox = gtk_hbox_new(TRUE, 0);
    gtk_box_pack_start(GTK_BOX(xsane.basic_adjustments.enhancement_buttons_container), hbox, FALSE, FALSE, 3);
    gtk_widget_show(hbox);

    xsane.basic_adjustments.rgb_default_button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, hbox, rgb_default_xpm, DESC_RGB_DEFAULT,
                                                 &xsane.enhancement_rgb_default, (void *)xsane_enhancement_rgb_default_callback);
    gtk_widget_add_accelerator(xsane.basic_adjustments.rgb_default_button, "clicked", xsane.accelerator_group, GDK_B, GDK_CONTROL_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

    xsane.basic_adjustments.negative_button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, hbox, negative_xpm, DESC_NEGATIVE,
                                                 &xsane.negative, (void *)xsane_enhancement_negative_callback);
    gtk_widget_add_accelerator(xsane.basic_adjustments.negative_button, "clicked", xsane.accelerator_group, GDK_N, GDK_CONTROL_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

    xsane.basic_adjustments.auto_enhancement_button = xsane_button_new_with_pixmap(xsane.main_window->window, hbox, enhance_xpm, DESC_ENH_AUTO,
                                          (void *)xsane_auto_enhancement_callback, NULL);
    gtk_widget_add_accelerator(xsane.basic_adjustments.auto_enhancement_button, "clicked", xsane.accelerator_group, GDK_A, GDK_CONTROL_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

    xsane.basic_adjustments.enhancement_restore_default_button = xsane_button_new_with_pixmap(xsane.main_window->window, hbox, default_enhancement_xpm, DESC_ENH_DEFAULT,
                                          (void *)xsane_enhancement_restore_default, NULL);
    gtk_widget_add_accelerator(xsane.basic_adjustments.enhancement_restore_default_button, "clicked", xsane.accelerator_group, GDK_0, GDK_CONTROL_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

    xsane.basic_adjustments.enhancement_restore_button = xsane_button_new_with_pixmap(xsane.main_window->window, hbox, restore_enhancement_xpm, DESC_ENH_RESTORE,
                                         (void *)xsane_enhancement_restore, NULL);
    gtk_widget_add_accelerator(xsane.basic_adjustments.enhancement_restore_button, "clicked", xsane.accelerator_group, GDK_R, GDK_CONTROL_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

    xsane.basic_adjustments.enhancement_store_button = xsane_button_new_with_pixmap(xsane.main_window->window, hbox, store_enhancement_xpm, DESC_ENH_STORE,
                                          (void *)xsane_enhancement_store, NULL);
    gtk_widget_add_accelerator(xsane.basic_adjustments.enhancement_store_button, "clicked", xsane.accelerator_group, GDK_plus, GDK_CONTROL_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

    /* AUTO_ENHANCEMENT_TYPE */
    {
      GtkWidget *xsane_enhancement_type_combo_box;

      hbox = gtk_hbox_new(FALSE, 5);
      gtk_box_pack_start(GTK_BOX(xsane.basic_adjustments.enhancement_buttons_container), hbox, FALSE, FALSE, 2);

      button = xsane_toggle_button_new_with_pixmap(xsane.main_window->window, hbox, enhance_xpm, DESC_ENH_ALWAYS,
                                                   &xsane.always_auto_enhance, (void *)xsane_always_auto_enhance_callback);
      gtk_widget_add_accelerator(button, "clicked", xsane.accelerator_group, GDK_A, GDK_SHIFT_MASK, (GtkAccelFlags)DEF_GTK_ACCEL_LOCKED);

      xsane_enhancement_type_combo_box = gtk_combo_box_new_text();
      //xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_enhancement_type_combo_box, "Auto Adjustment types");
      gtk_box_pack_end(GTK_BOX(hbox), xsane_enhancement_type_combo_box, TRUE, TRUE, 5);
      gtk_widget_show(xsane_enhancement_type_combo_box);

      gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_enhancement_type_combo_box), "Level and Color Balance");
      gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_enhancement_type_combo_box), "Level Only");
      gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_enhancement_type_combo_box), "Color Balance Only");

      gtk_combo_box_set_active(GTK_COMBO_BOX(xsane_enhancement_type_combo_box), xsane.enhancement_type);
      g_signal_connect(GTK_OBJECT(xsane_enhancement_type_combo_box), "changed", (GtkSignalFunc) xsane_enhancement_type_callback, NULL);

      gtk_widget_show(hbox);
    }

    /* reset free gamma curve? */
    {
      GtkWidget *xsane_reset_free_gamma_combo_box;

      hbox = gtk_hbox_new(FALSE, 5);
      gtk_box_pack_start(GTK_BOX(xsane.basic_adjustments.enhancement_buttons_container), hbox, FALSE, FALSE, 2);

      button = xsane_button_new_with_pixmap(xsane.main_window->window, hbox, default_enhancement_xpm, DESC_ENH_DEFAULT,
                                            (void *)xsane_enhancement_restore_default, NULL);

      xsane_reset_free_gamma_combo_box = gtk_combo_box_new_text();
      //xsane_back_gtk_set_tooltip(xsane.tooltips, xsane_reset_free_gamma_combo_box, "Auto Adjustment types");
      gtk_box_pack_end(GTK_BOX(hbox), xsane_reset_free_gamma_combo_box, TRUE, TRUE, 5);
      gtk_widget_show(xsane_reset_free_gamma_combo_box);

      /* Reset gamma curve */
      gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_reset_free_gamma_combo_box), "Adjustments and Curves");
      /* Do not reset gamma curve */
      gtk_combo_box_append_text(GTK_COMBO_BOX(xsane_reset_free_gamma_combo_box), "Adjustments Only");

      gtk_combo_box_set_active(GTK_COMBO_BOX(xsane_reset_free_gamma_combo_box), xsane.enhancement_type);
      g_signal_connect(GTK_OBJECT(xsane_reset_free_gamma_combo_box), "changed", (GtkSignalFunc) xsane_reset_free_gamma_callback, NULL);

      gtk_widget_show(hbox);
    }
  }
}

void xsane_update_basic_adjustment_tools()
{
  DBG(DBG_proc, "xsane_update_basic_adjustment_tools\n");
printf( "xsane_update_basic_adjustment_tools\n");

  /* test if scanner gamma table is selected */

  xsane.scanner_gamma_gray  = FALSE;
  if (xsane.device_options.well_known.gamma_vector >0)
  {
   const SANE_Option_Descriptor *opt;

    opt = xsane_get_option_descriptor(xsane.device_options.dev, xsane.device_options.well_known.gamma_vector);
    if (SANE_OPTION_IS_ACTIVE(opt->cap))
    {
      xsane.scanner_gamma_gray  = TRUE;
    }
  }

  xsane.scanner_gamma_color  = FALSE;
  if (xsane.device_options.well_known.gamma_vector_r >0)
  {
   const SANE_Option_Descriptor *opt;

    opt = xsane_get_option_descriptor(xsane.device_options.dev, xsane.device_options.well_known.gamma_vector_r);
    if (SANE_OPTION_IS_ACTIVE(opt->cap))
    {
      xsane.scanner_gamma_color  = TRUE;
    }
  }

  sane_get_parameters(xsane.device_options.dev, &xsane.param); /* update xsane.param */

  gtk_widget_hide(xsane.basic_adjustments.threshold_widget_container);
  gtk_widget_hide(xsane.basic_adjustments.gamma_container);
  gtk_widget_hide(xsane.basic_adjustments.brightness_container);
  gtk_widget_hide(xsane.basic_adjustments.contrast_container);
  gtk_widget_hide(xsane.basic_adjustments.enhancement_buttons_container);
  gtk_widget_hide(xsane.basic_adjustments.channel_gamma_container);
  gtk_widget_hide(xsane.basic_adjustments.channel_brightness_container);
  gtk_widget_hide(xsane.basic_adjustments.channel_contrast_container);

  {
    g_signal_handlers_block_by_func(GTK_OBJECT(xsane.basic_adjustments.rgb_default_button),
        (GtkSignalFunc) xsane_enhancement_rgb_default_callback,
        (gpointer)&xsane.enhancement_rgb_default);

    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane.basic_adjustments.rgb_default_button), xsane.enhancement_rgb_default);

    g_signal_handlers_unblock_by_func(GTK_OBJECT(xsane.basic_adjustments.rgb_default_button),
        (GtkSignalFunc) xsane_enhancement_rgb_default_callback,
        (gpointer)&xsane.enhancement_rgb_default);
  }

  {
    g_signal_handlers_block_by_func(GTK_OBJECT(xsane.basic_adjustments.negative_button),
        (GtkSignalFunc) xsane_enhancement_negative_callback,
        (gpointer)&xsane.negative);

    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xsane.basic_adjustments.negative_button), xsane.negative);

    g_signal_handlers_unblock_by_func(GTK_OBJECT(xsane.basic_adjustments.negative_button),
        (GtkSignalFunc) xsane_enhancement_negative_callback,
        (gpointer)&xsane.negative);
  }

  if (xsane.enable_color_management) /* do not show gamma widgets when color management is active ?? */
  {
    xsane.gamma            = 1.0;
    xsane.gamma_red        = 1.0;
    xsane.gamma_green      = 1.0;
    xsane.gamma_blue       = 1.0;
    xsane.brightness       = 0.0;
    xsane.brightness_red   = 0.0;
    xsane.brightness_green = 0.0;
    xsane.brightness_blue  = 0.0;
    xsane.contrast         = 0.0;
    xsane.contrast_red     = 0.0;
    xsane.contrast_green   = 0.0;
    xsane.contrast_blue    = 0.0;
    xsane.threshold        = 50.0;

    xsane.slider_gray.value[2]  = 100.0;
    xsane.slider_gray.value[1]  = 50.0;
    xsane.slider_gray.value[0]  = 0.0;
    xsane.slider_red.value[2]   = 100.0;
    xsane.slider_red.value[1]   = 50.0;
    xsane.slider_red.value[0]   = 0.0;
    xsane.slider_green.value[2] = 100.0;
    xsane.slider_green.value[1] = 50.0;
    xsane.slider_green.value[0] = 0.0;
    xsane.slider_blue.value[2]  = 100.0;
    xsane.slider_blue.value[1]  = 50.0;
    xsane.slider_blue.value[0]  = 0.0;
  }
  else
  {
    if (xsane.param.depth > 1)
    {
      xsane.slider_gray.active   = XSANE_SLIDER_ACTIVE; /* mark slider active */

      if (xsane.xsane_channels > 1)
      {
        gtk_widget_show(xsane.basic_adjustments.rgb_default_button);

        if (! xsane.enhancement_rgb_default)
        {
          gtk_widget_show(xsane.basic_adjustments.channel_gamma_container);
          gtk_widget_show(xsane.basic_adjustments.channel_brightness_container);
          gtk_widget_show(xsane.basic_adjustments.channel_contrast_container);
        }
      }
      else
      {
        gtk_widget_hide(xsane.basic_adjustments.rgb_default_button);
      }

      gtk_widget_show(xsane.basic_adjustments.gamma_container);
      gtk_widget_show(xsane.basic_adjustments.brightness_container);
      gtk_widget_show(xsane.basic_adjustments.contrast_container);

      if (xsane.medium_calibration) /* do not display "M R" when we are we running in medium calibration mode */
      {
        gtk_widget_hide(xsane.basic_adjustments.enhancement_restore_button);
        gtk_widget_hide(xsane.basic_adjustments.enhancement_store_button);
      }
      else
      {
        gtk_widget_show(xsane.basic_adjustments.enhancement_restore_button);
        gtk_widget_show(xsane.basic_adjustments.enhancement_store_button);
      }

      gtk_widget_show(xsane.basic_adjustments.enhancement_buttons_container);
    }
    else
    {
      switch (xsane.lineart_mode)
      {
        case XSANE_LINEART_STANDARD:
          break;

        case XSANE_LINEART_GRAYSCALE:
        case XSANE_LINEART_XSANE:
          if (xsane.device_options.well_known.threshold > 0)
          {
            gtk_widget_show(xsane.basic_adjustments.threshold_widget_container);
            xsane_threshold_changed();
          }
          break;

        default:
          break;
      }
    }
  }

printf( "done xsane_update_basic_adjustment_tools\n");
}

/* ---------------------------------------------------------------------------------------------------------------------- */

void xsane_resolution_list_callback(GtkWidget *widget, gpointer data)
{
 SANE_Word val;
 const gchar *name = gtk_widget_get_name(widget);
 int printer_resolution; 

  DBG(DBG_proc, "xsane_resolution_list_callback\n");

  switch (xsane.param.format)
  {
    case SANE_FRAME_GRAY:
      if (xsane.param.depth == 1)
      {
        printer_resolution = preferences.printer[preferences.printernr]->lineart_resolution;
      }
      else
      {
        printer_resolution = preferences.printer[preferences.printernr]->grayscale_resolution;
      }
    break;

    case SANE_FRAME_RGB:
    case SANE_FRAME_RED:
    case SANE_FRAME_GREEN:
    case SANE_FRAME_BLUE:
    default:
      printer_resolution = preferences.printer[preferences.printernr]->color_resolution;
    break;
  }       

  sscanf(gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)), "%d", &val);

  if (!strcmp(name, XSANE_GTK_NAME_RESOLUTION))
  {
    xsane.resolution   = val;
    xsane.resolution_x = val;
    xsane.resolution_y = val;

    xsane_set_resolution(xsane.device_options.well_known.dpi,   xsane.resolution);
    xsane_set_resolution(xsane.device_options.well_known.dpi_x, xsane.resolution_x);
    xsane_set_resolution(xsane.device_options.well_known.dpi_y, xsane.resolution_y);

    xsane.zoom   = xsane.resolution   / printer_resolution;
  }
  else if (!strcmp(name, XSANE_GTK_NAME_X_RESOLUTION))
  {
    xsane.resolution   = val;
    xsane.resolution_x = val;
    xsane_set_resolution(xsane.device_options.well_known.dpi_x, xsane.resolution_x);
    xsane.zoom = xsane.resolution / printer_resolution;
  }
  else if (!strcmp(name, XSANE_GTK_NAME_Y_RESOLUTION))
  {
    xsane.resolution_y = val;
    xsane_set_resolution(xsane.device_options.well_known.dpi_y, xsane.resolution_y);
    xsane.zoom = xsane.resolution / printer_resolution;
  }

  xsane_update_param(0);
}

/* ---------------------------------------------------------------------------------------------------------------------- */

static guint xsane_resolution_timer = 0;

/* ---------------------------------------------------------------------------------------------------------------------- */

gint xsane_resolution_timer_callback(GtkAdjustment *adj)
{
  if ((adj) && (!preferences.show_resolution_list)) /* make sure adjustment is valid */
  {
   float val = adj->value;

    adj->value += 1.0; /* we need this to make sure that set_value really redraws the widgets */
    gtk_adjustment_set_value(adj, val);
  }

  gtk_timeout_remove(xsane_resolution_timer);
  xsane_resolution_timer = 0;

 return 0; /* stop timeout */
}

void xsane_resolution_scale_update(GtkAdjustment *adj, double *val)
{
/* gtk does not make sure that the value is quantisized correct */
  float diff, old_val, new_val, quant;

  DBG(DBG_proc, "xsane_resolution_scale_update\n");

  quant = adj->step_increment;

  if (quant != 0)
  {
    new_val = adj->value;
    old_val = *val;
    diff = quant*((int) ((new_val - old_val)/quant));

    *val = old_val + diff;
    adj->value = *val;

#ifndef _WIN32
    /* the resolution slider gets almost unusable when we do this with win32 */
    if (xsane_resolution_timer)
    {
      gtk_timeout_remove(xsane_resolution_timer);
      xsane_resolution_timer = 0;
    }
    xsane_resolution_timer = gtk_timeout_add(XSANE_HOLD_TIME, (GtkFunction) xsane_resolution_timer_callback, (gpointer) adj);
#endif
  }
  else
  {
    *val = adj->value;
  }

  xsane_set_all_resolutions();
  xsane_update_param(0);
}

/* ---------------------------------------------------------------------------------------------------------------------- */

int xsane_resolution_widget_new(GtkWidget *parent, int well_known_option, double *resolution, const char *image_xpm[],
                                       const gchar *desc, const gchar *widget_name)
{
 GtkWidget *resolution_widget;
 const SANE_Option_Descriptor *opt;

  DBG(DBG_proc, "xsane_resolution_widget_new\n");

  opt = xsane_get_option_descriptor(xsane.device_options.dev, well_known_option);

  if (!opt)
  {
    return -1; /* options does not exist */
  }
  else
  {
    if (SANE_OPTION_IS_ACTIVE(opt->cap))
    {
      switch (opt->constraint_type)
      {
        case SANE_CONSTRAINT_RANGE:
        {
         double quant= 0.0;
         double min  = 0.0;
         double max  = 0.0;
         double val  = 0.0;
         SANE_Word value;

          gtk_widget_set_sensitive(xsane.show_resolution_list_widget, TRUE); 
          xsane_control_option(xsane.device_options.dev, well_known_option, SANE_ACTION_GET_VALUE, &value, 0); 

          switch (opt->type)
          {
            case SANE_TYPE_INT:
              min   = opt->constraint.range->min;
              max   = opt->constraint.range->max;
              quant = opt->constraint.range->quant;
              val   = (int) value;
            break;

            case SANE_TYPE_FIXED:
              min   = SANE_UNFIX(opt->constraint.range->min);
              max   = SANE_UNFIX(opt->constraint.range->max);
              quant = SANE_UNFIX(opt->constraint.range->quant);
              val   = SANE_UNFIX(value);
            break;

            default:
              DBG(DBG_error, "resolution_widget_new: %s %d\n", ERR_UNKNOWN_TYPE, opt->type);
          }

          if (quant == 0)
          {
            quant = 1.0;
          }

          *resolution = val; /* set backend predefined value */

          if (!preferences.show_resolution_list) /* user wants slider */ 
          {
            xsane_range_new_with_pixmap(xsane.main_window->window, GTK_BOX(parent), image_xpm, desc,
                                        min, max, quant, quant*10, 0, resolution, &resolution_widget,
                                        well_known_option, (void *)xsane_resolution_scale_update, SANE_OPTION_IS_SETTABLE(opt->cap));
          }
          else /* user wants list instead of slider */
          {
           SANE_Int max_items = 20;
           char **str_list;
           char str[16];
           int i;
           int j = 0;
           SANE_Word wanted_res;
           SANE_Word val = max;
           int res = max;
           double mul;
           int active = 0;

            xsane_control_option(xsane.device_options.dev, well_known_option, SANE_ACTION_GET_VALUE, &wanted_res, 0); 
            if (opt->type == SANE_TYPE_FIXED)
            {
              wanted_res = (int) SANE_UNFIX(wanted_res);
            }

            str_list = (char **)malloc((max_items + 1) * sizeof(str_list[0]));

            sprintf(str, "%d", (int) max);
            str_list[j++] = strdup(str);

            i=9;
            while ((j < max_items) && (res > 50) && (res > min) && (i > 0))
            {
              mul = ((double) i) / (i+1);
              res = (int) (max * mul);
              if  (res/mul == max)
              {
                res = xsane_find_best_resolution(well_known_option, res);
                sprintf(str, "%d", res);
                str_list[j++] = strdup(str);
                if (res >= wanted_res)
                {
                  val = res;
                }
              }
              i--;
            }

            i = 3;
            while ((j < max_items) && (res > 50) && (res > min))
            {
              mul = 1.0/i;
              res = max * mul;
              if (res/mul  == max)
              {
                res = xsane_find_best_resolution(well_known_option, res);
                sprintf(str, "%d", res);
                str_list[j++] = strdup(str);
                if (res >= wanted_res)
                {
                  val = res;
                }
              }
              i++;
            }

            str_list[j] = 0;
            sprintf(str, "%d", (int) val);

            for (active = 0; active < max_items; active++)
            {
              if (strcmp(str_list[active], str) == 0)
              {
                break;
              }
            }

            xsane_combo_box_new_with_pixmap(xsane.main_window->window, GTK_BOX(parent), image_xpm, desc, str_list, active, &resolution_widget, well_known_option,
                                              (void *)xsane_resolution_list_callback, SANE_OPTION_IS_SETTABLE(opt->cap), widget_name);

            free(str_list);
            *resolution = val;
            xsane_set_resolution(well_known_option, *resolution);
          }
        }
        break;

        case SANE_CONSTRAINT_WORD_LIST:
        {
         /* use a "list-selection" widget */
         SANE_Int items;
         char **str_list;
         char str[16];
         int j;
         SANE_Word val=0;
         int active = 0;

          gtk_widget_set_sensitive(xsane.show_resolution_list_widget, FALSE); 

          items = opt->constraint.word_list[0];
          str_list = (char **)malloc((items + 1) * sizeof(str_list[0]));
          switch (opt->type)
          {
            case SANE_TYPE_INT:
              for (j = 0; j < items; ++j)
              {
                sprintf(str, "%d", opt->constraint.word_list[j + 1]);
                str_list[j] = strdup(str);
              }
              str_list[j] = 0;
              xsane_control_option(xsane.device_options.dev, well_known_option, SANE_ACTION_GET_VALUE, &val, 0); 
              val = xsane_find_best_resolution(well_known_option, val); /* when backends uses default value not in list or range */
              sprintf(str, "%d", (int) val);
            break;

            case SANE_TYPE_FIXED:
              for (j = 0; j < items; ++j)
              {
                sprintf(str, "%d", (int) SANE_UNFIX(opt->constraint.word_list[j + 1]));
                str_list[j] = strdup(str);
               }
              str_list[j] = 0;
              xsane_control_option(xsane.device_options.dev, well_known_option, SANE_ACTION_GET_VALUE, &val, 0); 
              val = xsane_find_best_resolution(well_known_option, val); /* when backends uses default value not in list or range */
              sprintf(str, "%d", (int) SANE_UNFIX(val));
            break;

            default:
              DBG(DBG_error, "resolution_word_list_creation: %s %d\n", ERR_UNKNOWN_TYPE, opt->type);
          }

          for (active = 0; active < items; active++)
          {
            if (strcmp(str_list[active], str) == 0)
            {
              break;
            }
          }

          xsane_combo_box_new_with_pixmap(xsane.main_window->window, GTK_BOX(parent), image_xpm, desc,
                                            str_list, active, &resolution_widget, well_known_option,
                                            (void *)xsane_resolution_list_callback, SANE_OPTION_IS_SETTABLE(opt->cap), widget_name);
          free(str_list);
        }
        break;

        default:
         break;
      }	/* constraint type */

      return 0; /* everything is ok */

    } /* if resolution option active */

    return 1; /* not active */

  } /* if (opt) */
}

